/**
 * Created by xinxinran on 15/11/30.
 */
'use strict';

var socketIO, rooms = {}, i = 1,
    commonUtil = require('./commonUtil'),
    GomokuClient = require('./GomokuClient'),
    GomokuGamter = require('./GomokuGamer'),
    GameManager, allClients = {};

class GomokuRoom{
    constructor (roomName, roomIndex){
        this.roomName = roomName;
        this.firstPlayer = null;
        this.secondPlayer = null;

        this.roomP1Scroe = 0;
        this.roomP2Score = 0;
        this.p1Status = 0;
        this.p2Status = 0;

        this.watchers =[];

        this.roomInfo = {};

        this.roomClients = {};

        this.roomStatus = 0;
        this.roomNumber = roomIndex;

        this.gamer = new GomokuGamter(this);
    }

    resetRoom() {
        this.roomP1Scroe = 0;
        this.roomP2Score = 0;
        this._p1Status = 0;
        this._p2Status = 0;

        this.gamer.initRoomRule();
    }

    set roomStatus(status){
        this._roomStatus = status;
        if(status == 2){
            this.resetRoom();
        }
    }

    get roomStatus(){
        return this._roomStatus;
    }

    set p1Status(status){
        this._p1Status = status;
        this.checkStatus();
    }

    get p1Status(){
        return this._p1Status;
    }

    set p2Status(status){
        this._p2Status = status;
        this.checkStatus();
    }

    get p2Status(){
        return this._p2Status;
    }

    checkStatus(){
        var needClean = false;
        if(this._p1Status === 1 && this._p2Status === 1){
            this.p1Status = 2;
            this.p2Status = 2;

            this.gamer.startGame();

            needClean = true;
        }

        commonUtil.each(this.roomClients, function(sId, client){
            client.notifyPlayerStatus(this);
            needClean && client.sendGameCommand('clean');
        }, this);
    }

    makeRoomInfo() {
        var _this = this;
        this.roomInfo.p1 = this.firstPlayer ? this.firstPlayer.username : '?';
        this.roomInfo.p2 = this.secondPlayer ? this.secondPlayer.username : '?';

        this.roomInfo.watchers = [];
        commonUtil.each(this.watchers, function(_, wSocket){
            _this.roomInfo.watchers.push(wSocket.username);
        });

        this.roomInfo.status = this.roomStatus;
        this.roomInfo.roomName = this.roomName;
        this.roomInfo.roomNumber = this.roomNumber;

        return this.roomInfo;
    }
}

for(; i < 5; i++){
    rooms[i] = new GomokuRoom('房间' + i, i);
}

GameManager = {
    getRooms : function(){
        return commonUtil.each(rooms, function(_, r){
            return r.makeRoomInfo();
        }, null, true);
    },
    joinRoom : function(roomNum, mode, sessionId){
        var room = rooms[roomNum], client = allClients[sessionId];
        if(!room || !client){
            return;
        }
        if(mode === 'p'){
            if(room.roomStatus >= 2){
                mode = 'w';
            }else{
                client.roomNumber = room.roomNumber;
                room.roomClients[client.sessionId] = client;

                if(room.roomStatus === 0){
                    room.roomStatus = 1;
                    room.firstPlayer = client;
                }else{
                    room.roomStatus = 2;
                    room.secondPlayer = client;
                    commonUtil.each(room.roomClients, function(sId, client){
                        client.enterRoom(room);
                    });
                }
            }
        }
        if(mode === 'w'){
            client.roomNumber = room.roomNumber;
            room.watchers.push(client);
            room.roomClients[client.sessionId] = client;
            if(room.roomStatus === 2){
                client.enterRoom(room);
            }
        }

        commonUtil.each(allClients, function(sId, client){
            client.pushRoom(GameManager.getRooms());
        });

        commonUtil.each(room.roomClients, function(sId, thisClient){
            thisClient.sendMessage(client.username, 'muted', 'center', '进入了房间,前来' + (mode === 'p' ? '对战' : '观战') );
        });
    },
    leaveRoom : function(roomNum, sessionId){
        var room = rooms[roomNum], client = room && room.roomClients[sessionId];

        if(!room || !client){
            return;
        }

        if(room.firstPlayer === client){
            room.firstPlayer = room.secondPlayer;
            room.secondPlayer = null;
        }else if(room.secondPlayer === client){
            room.secondPlayer = null;
        }else{
            room.watchers.splice(room.watchers.indexOf(client), 1);
            client.outRoom(room);
        }

        if(!(room.firstPlayer && room.secondPlayer)){
            if(room.firstPlayer || room.secondPlayer){
                commonUtil.each(room.roomClients, function(sId, client){
                    client.outRoom(room);
                });
                room.roomStatus = 1
            }else{
                room.roomStatus = 0;
            }
        }

        client.roomNumber = 0;
        commonUtil.each(allClients, function(sId, client){
            client.pushRoom(GameManager.getRooms());
        });

        commonUtil.each(room.roomClients, function(sId, thisClient){
            thisClient.sendMessage(client.username, 'muted', 'center', '离开了房间' );
        });
    },
    getReady : function(roomNum, sId){
        var room = rooms[roomNum];
        if(!room || !room.roomClients[sId]){
            return;
        }

        if(room.firstPlayer.sessionId === sId){
            room.p1Status = 1;
        }else if(room.secondPlayer.sessionId === sId){
            room.p2Status = 1;
        }
    },
    playStep : function(r, x, y, t){
        var room = rooms[r];
        if(!room){
            return;
        }

        room.gamer.getChess(x, y, t);
    },

    getRoomChessMap : function(r){
        var room = rooms[r];
        if(!room){
            return;
        }

        return {map : room.gamer.positionsObj, last : room.gamer.positionStep[room.gamer.positionStep.length - 1]};
    },

    myLose : function(r, sId){
        var room = rooms[r];
        if(!room){
            return;
        }

        if(room.firstPlayer.sessionId === sId){
            room.gamer.endRound(2);
        }else if(room.secondPlayer.sessionId === sId){
            room.gamer.endRound(1);
        }
    },

    roomChat : function(r, userName, content){
        var room = rooms[r];
        if(!room){
            return;
        }

        commonUtil.each(room.roomClients, function(sId, client){
            var isSelf = client.username === userName ;
            client.sendMessage('[' + userName + '] 说 : ', isSelf ? 'success' : 'info', isSelf ? 'right' : 'left', content);
        });
    },

    requestDraw : function(r, sId){
        var room = rooms[r], dToken = commonUtil.uuid(16, 16), needRefreshStatus = false;
        if(!room){
            return;
        }

        if(room.gamer.requestToken){
            return;
        }

        room.gamer.requestToken = dToken;

        if(room.firstPlayer.sessionId === sId){
            room.firstPlayer.statusDesc = '申请和棋';
            room.secondPlayer.statusDesc = '和棋确认中...';
            room.secondPlayer.sendGameCommand('sysNotice', {title : '申请和棋', noticeType : 'primary', content : room.firstPlayer.username + ' 申请和棋,是否同意?',
                needYN : true, backCommand : {cmd: 'confirmDraw', data : {t : dToken, s: sId}, noCmd : 'cancelDraw', noData : {t : dToken, s: sId}}});
            needRefreshStatus = true;
        }else if(room.secondPlayer.sessionId === sId){
            room.secondPlayer.statusDesc = '申请和棋';
            room.firstPlayer.statusDesc = '和棋确认中...';
            room.firstPlayer.sendGameCommand('sysNotice', {title : '申请和棋', noticeType : 'primary', content : room.secondPlayer.username + ' 申请和棋,是否同意?',
                needYN : true, backCommand : {cmd: 'confirmDraw', data : {t : dToken, s: sId}, noCmd : 'cancelDraw', noData : {t : dToken, s: sId}}});
            needRefreshStatus = true;
        }

        if(needRefreshStatus){
            commonUtil.each(room.roomClients, function(sId, client){
                client.notifyPlayerStatus(room);
            });
        }
    },

    cancelDraw : function(r, t, s){
        var room = rooms[r];
        if(!room){
            return;
        }

        if(room.gamer.requestToken === t){
            room.gamer.requestToken = null;
            room.secondPlayer.statusDesc = '';
            room.firstPlayer.statusDesc = '';

            commonUtil.each(room.roomClients, function(sId, client){
                if(client.sessionId === s){
                    client.sendNotice('取消和棋', '对方不同意和棋,请继续对战', 'info');
                }
                client.notifyPlayerStatus(room);
            });
        }
    },

    drawGame : function(r, t, s){
        var room = rooms[r];
        if(!room){
            return;
        }

        if(room.gamer.requestToken === t){
            room.gamer.requestToken = null;
            room.secondPlayer.statusDesc = '';
            room.firstPlayer.statusDesc = '';
            if(room.firstPlayer.sessionId === s || room.secondPlayer.sessionId === s){
                room.gamer.endRound(0);
            }
        }
    },

    requestBack : function(r, client){
        var room = rooms[r], isP1, oppoClient, dToken = commonUtil.uuid(16, 16);
        if(!room){
            return;
        }

        if(room.gamer.requestToken || !room.gamer.positionStep.length){
            return;
        }

        if((isP1 = (room.secondPlayer !== client)) && room.firstPlayer !== client){
            return;
        }

        if((room.gamer.p1Color === room.gamer.nowColor) ^ isP1){
            room.gamer.requestToken = dToken;
            oppoClient = isP1 ? room.secondPlayer : room.firstPlayer;
            client.statusDesc = '申请悔棋';
            oppoClient.statusDesc = '悔棋确认中...';

            oppoClient.sendGameCommand('sysNotice',{title : '申请悔棋', noticeType : 'primary', content : client.username + ' 申请悔棋,是否同意?',
                needYN : true, backCommand : {cmd: 'confirmBack', data : {t : dToken, s : client.sessionId}, noCmd : 'cancelBack', noData : {t : dToken, s : client.sessionId}}});

            commonUtil.each(room.roomClients, function(sId, client){
                client.notifyPlayerStatus(room);
            });
        }else{
            client.sendNotice('不能悔棋', '对方已经落子, 不能申请悔棋..', 'warning');
        }
    },

    cancelBack : function(r, t, s){
        var room = rooms[r];
        if(!room){
            return;
        }

        if(room.gamer.requestToken === t){
            room.gamer.requestToken = null;
            room.secondPlayer.statusDesc = '';
            room.firstPlayer.statusDesc = '';

            commonUtil.each(room.roomClients, function(sId, client){
                if(client.sessionId === s){
                    client.sendNotice('取消悔棋', '对方不同意悔棋,请继续对战', 'info');
                }
                client.notifyPlayerStatus(room);
            });
        }
    },

    backChess : function(r, t, s){
        var room = rooms[r], isP2;
        if(!room){
            return;
        }

        if(room.gamer.requestToken === t){
            room.gamer.requestToken = null;
            room.secondPlayer.statusDesc = '';
            room.firstPlayer.statusDesc = '';
            if((isP2 = (room.secondPlayer.sessionId === s)) || room.firstPlayer.sessionId === s){
                room.gamer.backChess(isP2 + 1);
            }
        }
    }
};

exports.processIO = function(io){
    socketIO = io;
    socketIO.on('connection', function(socket){
        var client = new GomokuClient(socket, GameManager);
        socket.on('disconnect', function(){
            if(client.roomNumber){
                GameManager.leaveRoom(client.roomNumber, client.sessionId);
            }
            client.destroy();
            socket = null;
            delete allClients[client.sessionId];
            client = null;
        });

        allClients[client.sessionId] = client;
    });
};